/*
XPTracker - Alternative Agile Tracking Tool
Copyright (C) 2006-2009  Stephen Starkey

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
*/
package org.xptracker.web;

import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.SimpleError;
import org.apache.commons.logging.LogFactory;
import org.xptracker.domain.Story;
import org.xptracker.domain.StoryCategory;
import org.xptracker.persistence.PersistenceManager;
import org.xptracker.util.IoUtil;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;

@UrlBinding("/Categories.action")
public class CategoriesActionBean extends StandardActionBean {
  private List<StoryCategory> categories;
  private FileBean categoryImage;
  private String categoryId;
  private String type;

  public List<StoryCategory> getCategories() {
    return categories;
  }

  public void setCategories(List<StoryCategory> categories) {
    this.categories = categories;
  }

  public FileBean getCategoryImage() {
    return categoryImage;
  }

  public void setCategoryImage(FileBean categoryImage) {
    this.categoryImage = categoryImage;
  }

  public String getCategoryId() {
    return categoryId;
  }

  public void setCategoryId(String categoryId) {
    this.categoryId = categoryId;
  }

  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }

  @DefaultHandler
  public Resolution listCategories() {
    return new ForwardResolution("/admin/categories.jsp");
  }

  @HandlesEvent("UpdateImage")
  public Resolution changeImage() {
    try {
    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        StoryCategory category = domain.loadEntity(StoryCategory.class, categoryId);
        category.setContentType(categoryImage.getContentType());
        try {
          category.setImage(IoUtil.getByteArray(categoryImage.getInputStream()));
          categoryImage.delete();
          receiver.update(category);
          getContext().getMessages().add(new SimpleMessage("Image Added to category ''" + category.getName() + "''"));
          return new RedirectResolution(CategoriesActionBean.class);
        } catch (IOException e) {
          throw new IllegalStateException(e);
        }
      }
    });
    } catch(IllegalStateException e) {
      LogFactory.getLog(getClass()).warn("Error storing category image", e);
      getContext().getValidationErrors().addGlobalError(new SimpleError(e.getCause().getMessage()));
      return new RedirectResolution(CategoriesActionBean.class);
    }
  }

  @HandlesEvent("DisplayCategoryImage")
  public Resolution displayImage() {
    StoryCategory category = domain.loadEntity(StoryCategory.class, categoryId);
    return new StreamingResolution(category.getContentType(), new ByteArrayInputStream(category.getImage()));
  }

  @HandlesEvent("Add")
  public Resolution addCategory() {
    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        String categoryName = param("name");
        StoryCategory category = domain.loadCategory(categoryName);
        if (category == null) {
          receiver.insert(new StoryCategory(categoryName));
          getContext().getMessages().add(new SimpleMessage("Added category ''{0}''", categoryName));
        } else {
          getContext().getValidationErrors().add("name", alreadyExistsError("Category", categoryName));
        }
        return new RedirectResolution(CategoriesActionBean.class).flash(CategoriesActionBean.this);
      }
    });
  }

  @HandlesEvent("Delete")
  public Resolution deleteCategory() {
    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        String categoryId = param("uuid");
        StoryCategory category = loadEntity(StoryCategory.class, categoryId);
        if (category != null) {
          List<Story> stories = domain.listStoriesByCategory(category);
          for(Story story: stories) {
            story.getCategories().remove(category);
            receiver.update(story);
            getContext().getMessages().add(new SimpleMessage("Category removed from story {0}", story.getExtId()));
          }
          receiver.remove(category);
          getContext().getMessages().add(new SimpleMessage("Deleted category"));
        } else {
          getContext().getValidationErrors().add("name", new SimpleError("Category ''{1}'' does not exist.", categoryId));
        }
        return new RedirectResolution(CategoriesActionBean.class).flash(CategoriesActionBean.this);
      }
    });
  }

  @HandlesEvent("UpdateType")
  public Resolution updateType() {
    return persistenceManager.inTransaction(new PersistenceManager.UpdateHandler<Resolution>() {
      public Resolution doUpdate(PersistenceManager.UpdateReceiver receiver) {
        StoryCategory category = loadEntity(StoryCategory.class, categoryId);
        category.setType(type);
        receiver.update(category);
        return new StreamingResolution("text/plain", categoryId);
      }
    });
  }

  @Before(stages=LifecycleStage.BindingAndValidation)
  public void provideCategories() {
    this.categories = domain.listCategories();
  }
}
